package main

import (
	"bufio"
	"flag"
	"fmt"
	"net"
	"os"
	"strings"
	"io"
)



var port = flag.String("port", "8080", "Port")
var ip = flag.String("ip", "127.0.0.1", "ip")

var flagLogVerbose  = flag.Bool("V", false, "Log Verbose")
var isClient  = flag.Bool("C", false, "Client")
var isClientFile  = flag.Bool("CF", false, "Client")
var fileNmae  = flag.String("file", "send.txt", "Client")
var isServer  = flag.Bool("S", false, "Server")

var  kafkaServerII string
var isOpenLogVerbose = false
func main() {
	flag.Parse()

	if *isClient{
		println("客户端")
		mainClient()

	}else if *isClientFile {
		println("客户端 发送文件")
		mainClientFile() 
	}else if *isServer {
		println("服务端")
		mainServer()
	}else{

		println("请选择客户端(-C),客户端发送文件(-CF)还是服务端配置(-S)")
		println("客户端发送文件(-CF) .\socket-tool.exe -CF -file send.txt 如果不写-file 默认就发送程序下面的 send.txt")
	}
}


func process(conn net.Conn) {
	// 处理完关闭连接
	defer conn.Close()

	// 针对当前连接做发送和接受操作
	for {
		reader := bufio.NewReader(conn)
		var buf [128]byte
		n, err := reader.Read(buf[:])
		if err != nil {
			fmt.Printf("read from conn failed, err:%v\n", err)
			break
		}

		recv := string(buf[:n])
		fmt.Printf("收到的数据：%v\n", recv)

		// 将接受到的数据返回给客户端
		_, err = conn.Write([]byte("ok"))
		if err != nil {
			fmt.Printf("write from conn failed, err:%v\n", err)
			break
		}
	}
}

func mainServer() {
	address := fmt.Sprintf(":%v",*port)
	fmt.Printf("%v\n", address)
	// 建立 tcp 服务
	listen, err := net.Listen("tcp", address)
	if err != nil {
		fmt.Printf("listen failed, err:%v\n", err)
		return
	}

	for {
		// 等待客户端建立连接
		conn, err := listen.Accept()
		if err != nil {
			fmt.Printf("accept failed, err:%v\n", err)
			continue
		}
		// 启动一个单独的 goroutine 去处理连接
		go process(conn)
	}
}



func mainClient() {
	address := fmt.Sprintf("%v:%v",*ip,*port)
	fmt.Printf("%v\n", address)
	// 1、与服务端建立连接
	conn, err := net.Dial("tcp",address )
	if err != nil {
		fmt.Printf("conn server failed, err:%v\n", err)
		return
	}
	// 2、使用 conn 连接进行数据的发送和接收
	input := bufio.NewReader(os.Stdin)
	for {
		s, _ := input.ReadString('\n')
		s = strings.TrimSpace(s)
		if strings.ToUpper(s) == "Q" {
			return
		}

		_, err = conn.Write([]byte(s))
		if err != nil {
			fmt.Printf("send failed, err:%v\n", err)
			return
		}
		// 从服务端接收回复消息
		var buf [1024]byte
		n, err := conn.Read(buf[:])
		if err != nil {
			fmt.Printf("read failed:%v\n", err)
			return
		}
		fmt.Printf("收到服务端回复:%v\n", string(buf[:n]))
	}
}

func mainClientFile() {
    address := fmt.Sprintf("%v:%v", *ip, *port)
    fmt.Printf("%v\n", address)
    // 1、与服务端建立连接
    conn, err := net.Dial("tcp", address)
    if err != nil {
        fmt.Printf("conn server failed, err:%v\n", err)
        return
    }
    defer conn.Close()

    file, err := os.Open(*fileNmae)
    if err != nil {
        fmt.Printf("open file failed, err:%v\n", err)
        return
    }
    defer file.Close()

    fileInfo, err := file.Stat()
    if err != nil {
        fmt.Printf("get file info failed, err:%v\n", err)
        return
    }

    fileSize := fileInfo.Size()
    _, err = fmt.Fprintf(conn, "FILE %d\n", fileSize)
    if err != nil {
        fmt.Printf("send file size failed, err:%v\n", err)
        return
    }

    // 等待服务器确认
    var confirmationMessage [1024]byte
    n, err := conn.Read(confirmationMessage[:])
    if err != nil && err != io.EOF {
        fmt.Printf("read confirmation message failed, err:%v\n", err)
        return
    }
    confirmation := string(confirmationMessage[:n])
    fmt.Printf("Recv Server: %s\n", confirmation)

    buffer := make([]byte, 1024)
    for {
        n, err := file.Read(buffer)
        if err != nil && err != io.EOF {
            fmt.Printf("read file failed, err:%v\n", err)
            return
        }
        _, err = conn.Write(buffer[:n])
        if err != nil {
            fmt.Printf("send data failed, err:%v\n", err)
            return
        }
        if n < len(buffer) {
            break
        }
    }
}
